import { CCObject, Component, IVec2Like, Node, Vec3 } from "cc";

/**
 * 目标是否为类类型
 * @param target 判断目标
 * @return 返回结果（类型约束）
 */
export function isClass(target: any): target is Class<any> {
    return typeof target === 'function' && /^class\s/.test(Function.prototype.toString.call(target));
}

/**
 * 目标是否为组件类型或其衍生类
 * @param target 判断目标
 * @return 返回结果（类型约束）
 */
export function isComponent(target: any): target is Class<Component> {
    return target === Component || target.prototype instanceof Component;
}

/**
 * 设置CC对象标志位
 * @param target 设置目标
 * @params flags 标志位罗列
 * @return 源目标
 */
export function setFlags<T extends CCObject>(target: T, ...flags: CCObject.Flags[]): T {
    flags.forEach(flag => target._objFlags |= flag);
    return target;
}

/**
 * 清除CC对象标志位
 * @param target 设置目标
 * @params flags 标志位罗列
 * @return 源目标
 */
export function clearFlags<T extends CCObject>(target: T, ...flags: CCObject.Flags[]): T {
    flags.forEach(flag => target._objFlags &= ~flag);
    return target;
}

/**
 * 判断CC对象是否含有标志位
 * @param target 判断目标
 * @param flag 判断标志位
 * @return 判断结果
 */
export function checkFlags(target: CCObject, flag: CCObject.Flags): bool.res {
    return !!(target._objFlags & flag);
}

/**
 * 判断CC对象是否已经加载
 * @param target 判断目标
 * @return 判断结果
 */
export function IsOnLoadCalled(target: CCObject): bool.res {
    return checkFlags(target, CCObject.Flags.IsOnLoadCalled);
}

/**
 * 在场景树中设置节点的显示属性
 * @param node 目标节点
 * @param show 显示或隐藏
 */
export function displayInHierarch(node: Node, show: boolean): void {
    show ? setFlags(node, CCObject.Flags.HideInHierarchy) : clearFlags(node, CCObject.Flags.HideInHierarchy);
}

/** 
 * （平移）变换节点到另一个节点下
 * @param node 目标节点
 * @param parent 新的父节点
 * @param offset 并产生平移，默认不偏移
 */
export function traverse(node: Node, parent: Node, offset?: IVec2Like): void {
    node.getWorldPosition(_vec3);
    node.parent = parent;
    node.setWorldPosition(_vec3);
    if (offset) {
        const { x, y } = node.position;
        node.setPosition(x + offset.x, y + offset.y);
    }
}
const _vec3 = new Vec3;